File input
Allows users to select and upload files from their devices
#Examples
#Default
The standard way to let users upload a single file. It shows a button that triggers the device's file selection dialog. After selection, displays the chosen file name.
const [files, setFiles] = useState<FileList | null>(null);
return (
<FileInput value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
);#Don't List Files
Ideal when file names are irrelevant to the user's task.
const [files, setFiles] = useState<FileList | null>(null);
useEffect(() => {
console.log(files);
}, [files]);
return (
<FileInput listFiles={false} value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
);#Hide Button
Best Practice:
- Embed the input within a custom element.
- Visually indicate the upload zone with clear instructions and cues.
const [files, setFiles] = useState<FileList | null>(null);
const hasFiles = files != undefined && files != null && files.length > 0;
return (
<FileInput hideButton={hasFiles} value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
);#Multiple Files
When users need to upload multiple files at once.
Best Practice:
- Allow users to select several files simultaneously.
- Display the number of selected files and their names in a legible list.
- Clearly state the maximum number of permitted files.
const [files, setFiles] = useState<FileList | null>(null);
return (
<FileInput multiple value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose files
</FileInput>
);#File Type
When you want to restrict the types of files users can upload (e.g., images only).
Best Practice:
- Specify acceptable file types (e.g., png, jpg)
const [files, setFiles] = useState<FileList | null>(null);
return (
<FileInput
accept=".png, .jpg, .jpeg"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
Choose file
</FileInput>
);#Form Element Wrapper
Integrate the file input seamlessly into forms, aligning with other form elements.
Best Practice:
- Apply consistent styling with other form controls (input fields, buttons, etc.).
- Ensure proper spacing and alignment within the form.
- Provide informative error messages if uploads fail or file types are invalid.
const [files, setFiles] = useState<FileList | null>(null);
const hasFiles = files != undefined && files != null && files.length > 0;
return (
<FormElementWrapper
name="file"
label="Choose File"
error={"Selected file invalid"}
invalid={hasFiles && files[0].size > 1000}
>
<FileInput value={files} onChange={(x: FileList | null) => setFiles(x)}>
<Icon>
<IconAdd />
</Icon>
Add
</FileInput>
</FormElementWrapper>
);#Variant
Choose the appearance of the file input button to match your design.
Best Practice:
- Prioritize accessibility and maintain clear "button" affordance.
- See Button variant
const [filesPrimary, setFilesPrimary] = useState<FileList | null>(null);
const [filesSecondary, setFilesSecondary] = useState<FileList | null>(null);
const [filesDefault, setFilesDefault] = useState<FileList | null>(null);
const [filesBorderless, setFilesBorderless] = useState<FileList | null>(null);
const [filesCtaPrimary, setFilesCtaPrimary] = useState<FileList | null>(null);
const [filesCtaSecondary, setFilesCtaSecondary] = useState<FileList | null>(null);
const [filesCtaDefault, setFilesCtaDefault] = useState<FileList | null>(null);
return (
<>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="primary"
value={filesPrimary}
onChange={(x: FileList | null) => setFilesPrimary(x)}
>
Primary
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="secondary"
value={filesSecondary}
onChange={(x: FileList | null) => setFilesSecondary(x)}
>
Secondary
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput value={filesDefault} onChange={(x: FileList | null) => setFilesDefault(x)}>
Default
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="borderless"
value={filesBorderless}
onChange={(x: FileList | null) => setFilesBorderless(x)}
>
Borderless
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="ctaPrimary"
value={filesCtaPrimary}
onChange={(x: FileList | null) => setFilesCtaPrimary(x)}
>
Primary
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="ctaSecondary"
value={filesCtaSecondary}
onChange={(x: FileList | null) => setFilesCtaSecondary(x)}
>
Secondary
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="ctaDefault"
value={filesCtaDefault}
onChange={(x: FileList | null) => setFilesCtaDefault(x)}
>
Default
</FileInput>
</div>
</>
);#Sizes
Adjust the size of the file input to fit different contexts and layouts.
Best Practice:
- Adjust the file input's size for different layouts and screen sizes.
- Maintain visual consistency with other elements.
- Ensure the input is easily clickable on all devices.
const [filesSmall, setFilesSmall] = useState<FileList | null>(null);
const [filesMedium, setFilesMedium] = useState<FileList | null>(null);
const [filesLarge, setFilesLarge] = useState<FileList | null>(null);
return (
<>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
size="small"
value={filesSmall}
onChange={(x: FileList | null) => setFilesSmall(x)}
>
Small
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
size="medium"
value={filesMedium}
onChange={(x: FileList | null) => setFilesMedium(x)}
>
Medium
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
size="large"
value={filesLarge}
onChange={(x: FileList | null) => setFilesLarge(x)}
>
Large
</FileInput>
</div>
</>
);#Full Width
Maximize the width of the file input, especially in wide content areas.
Best Practice:
- Expand the input to the full width of its container.
- Use cautiously, especially on smaller screens.
const [files, setFiles] = useState<FileList | null>(null);
return (
<FileInput fullWidth value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
);#Loading
Provide visual feedback while the file is being uploaded. Use Spinner to clearly communicate the upload status to the user.
const [files, setFiles] = useState<FileList | null>(null);
return (
<>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput loading value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
</div>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput
loading
variant="ctaDefault"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
Choose file
</FileInput>
</div>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput
loading
ariaLabel="Loading"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
<Icon>
<IconAdd />
</Icon>
</FileInput>
</div>
</>
);#Disabled
Prevent user interaction when the file input is not available.
const [files, setFiles] = useState<FileList | null>(null);
return (
<>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput disabled value={files} onChange={(x: FileList | null) => setFiles(x)}>
Disabled
</FileInput>
</div>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput
disabled
variant="ctaDefault"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
Disabled
</FileInput>
</div>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput
disabled
ariaLabel="Add file"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
<Icon>
<IconAdd />
</Icon>
</FileInput>
</div>
</>
);#Properties
| Property | Description | Defined | Value |
|---|---|---|---|
valueRequired | | objectValue of the form control | ||
onChangeRequired | functionCallback for onChange event | ||
nameOptional | stringName applied to the form control | ||
idOptional | stringId applied to the form control | ||
invalidOptional | booleanIs the form control invalid | ||
onBlurOptional | functionCallback for onBlur event | ||
aria-labelOptional | stringLabel of the form control | ||
aria-describedbyOptional | stringID of an an element that describes what the form control is for | ||
aria-labelledbyOptional | stringID of an an element that labels this form control | ||
childrenOptional | elementText and icons to be displayed inside the button. | ||
listFilesOptional | booleanShould selected files be listed on screen | ||
hideButtonOptional | booleanShould the button be hidden | ||
multipleOptional | booleanAllow multiple files to be selected | ||
acceptOptional | stringSpecify accepted file extensions | ||
disabledOptional | booleanCan the file input button be clicked | ||
sizeOptional | "large" | "medium" | "small"Controls the size of the button and listed files - defaults to medium | ||
fullWidthOptional | booleanShould the file input button fill full width? | ||
variantOptional | "borderless" | "ctaDefault" | "ctaPrimary" | "ctaSecondary" | "default" | "destructive" | "primary" | "secondary"How should the file input button look | ||
loadingOptional | booleanShould the file input button show a loading indicator | ||
autoFocusOptional | booleanFocus the file input immediately when rendering the first time | ||
ariaHiddenOptional | booleanIndicates whether the element is exposed to an accessibility API. | ||
ariaLabelOptional | stringDescribe what happens if the file input is clicked | ||
ariaLabelledByOptional | stringID of an element that describes what happens if the file input is clicked | ||
ariaDescribedByOptional | stringIDs of the elements that describe the file input's function | ||
classNameOptional | stringCustom className that's applied to the outermost element (only intended for special cases) | ||
styleOptional | objectStyle object to apply custom inline styles (only intended for special cases) | ||
tabIndexOptional | numberTab index of the outermost HTML element of the component | ||
onKeyDownOptional | functionCallback for onKeyDown event | ||
onMouseDownOptional | functionCallback for onMouseDown event | ||
onMouseEnterOptional | functionCallback for onMouseEnter event | ||
onMouseLeaveOptional | functionCallback for onMouseLeave event | ||
onFocusOptional | functionCallback for onFocus event | ||
data-componentOptional | stringName of the component. Should only be set by components since it needs to stable. Used to track component usage | ||
data-observe-keyOptional | stringUnique string, used by external script e.g. for event tracking |
#Guidelines
#Best practices
#Do not use when
#Accessibility
Explore detailed guidelines for this component: Accessibility Specifications